import os
import time
from threading import Thread
import xlwt
from urllib import request
import ddddocr
from selenium.common import NoAlertPresentException
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.chrome.options import Options  # 引入Chrome的配置
import pandas as pd
from pandas import ExcelWriter
from openpyxl.utils import get_column_letter
import numpy as np
import random


def recognize(web):  # 验证码识别
    # time.sleep(random.randint(2, 10))
    img_src = web.find_element(By.XPATH, '//*[@id="icode"]').get_attribute("src")  # 获取图片的全部链接
    request.urlretrieve(img_src, "photo.jpg")  # 将图片下载到同路径下
    ocr = ddddocr.DdddOcr()
    with open('photo.jpg', 'rb') as f:
        img_bytes = f.read()  # 读完的格式是一个二进制
    res = ocr.classification(img_bytes)
    os.remove('photo.jpg')
    web.find_element(By.XPATH, '//*[@id="txtSecretCode"]').send_keys(res)


def scrapy_excel(username, password, schoolyear, semester):

    # url = url_link  # 函数的第一个参数中要传入url_link参数
    url = "http://210.30.208.218/"

    data_list = []
    # TODO: 上网人数多时怎么办 -> 刷新重新进入或者多开网页 / 不同浏览器同时开 / 调整最大等待时间 / 多开网站
    ch_options = Options()
    ch_options.add_argument("--headless")  # 为Chrome配置无头模式
    web = Chrome(chrome_options=ch_options)
    # web = Chrome()
    # web.maximize_window()

    web.get(url)
    web.find_element(By.XPATH, '//*[@id="txtUserName"]').send_keys(username)
    while True:  # 因为报错后只用重新输入密码和验证码，不需要输入账号
        web.find_element(By.XPATH, '//*[@id="TextBox2"]').send_keys(password)
        recognize(web)
        web.find_element(By.XPATH, '//*[@id="Button1"]').click()  # 点击登录
        if verification_code(web) == "验证码正确":  # 不传web会报错 因为web的作用范围只有默认函数
            break
        else:
            continue

    element = web.find_element(By.XPATH, '//*[@id="headDiv"]/ul/li[5]/ul/li[4]/a')  # 点击查询成绩
    web.execute_script("arguments[0].click();", element)

    iframe_path = '/html/body/div/div[2]/div[2]/div/iframe'  # 先定位到iframe
    elem = web.find_element(By.XPATH, iframe_path)
    web.switch_to.frame(elem)  # 再将定位对象传给switch_to_frame()方法

    # 定位下拉框,实例化select方法
    ele = web.find_element(By.ID, "ddlXN")
    select_ele = Select(ele)
    # 通过下拉元素的value选择下拉元素
    select_ele.select_by_value(schoolyear)

    # 第一学期为2 第二学期为3
    web.find_element(By.XPATH, '//*[@id="ddlXQ"]/option[' + str(int(semester) + 1) + ']').click()

    element3 = web.find_element(By.XPATH, "/html/body/form/div[1]/div[3]/p[1]/input[1]")
    web.execute_script("arguments[0].click();", element3)  # 点击学期成绩

    quantity = len(web.find_elements(By.CSS_SELECTOR, 'table.datelist>tbody>tr'))  # 获取表格的长度
    # print(quantity)  # 查看中途是否被Kill

    for i in range(2, quantity + 1):
        data = []
        for j in range(1, 21):
            if j in [3, 6, 10, 12, 15, 16, 17, 19, 20]:
                continue
            else:
                aa = web.find_element(By.XPATH, '//*[@id="Datagrid1"]/tbody/tr[%s]/td[' % i + str(j) + ']').text
                data.append(aa)
        data_list.append(data)

    book = xlwt.Workbook(encoding="utf-8", style_compression=0)  # 创建workbook对象
    sheet = book.add_sheet('ssssss', cell_overwrite_ok=True)  # 创建工作表
    # col = ("学年", "学期", "课程代码", "课程名称", "课程性质", "课程归属", "学分", "绩点", "平时成绩", "期中成绩",
    #        "期末成绩", "实验成绩", "成绩", "辅修标记", "补考成绩", "卷面补考成绩", "重修成绩", "开课学院", "备注", "重修标记")
    col = ("学年", "学期", "课程名称", "课程性质", "学分", "绩点", "平时成绩", "期末成绩", "成绩", "辅修标记", "开课学院")
    # 表头字段的写入
    for i in range(0, len(col)):
        sheet.write(0, i, col[i])  # 列名
    # 数据字段的写入
    for i in range(0, len(data_list)):
        # print("第{}条".format(i + 1))
        data = data_list[i]
        for j in range(0, len(data)):
            sheet.write(i + 1, j, data[j])
    book.save('成绩.xlsx')  # 保存数据表
    print("成绩已保存在Excel中")

    web.close()


def verification_code(web):
    try:  # 识别错误时应点击alert弹窗，之后再重新填写密码和验证码
        if web.switch_to.alert.text == "验证码不正确！！":
            web.switch_to.alert.accept()  # 接收弹窗
    except NoAlertPresentException:
        return "验证码正确"


def excel_auto_column(df: pd.DataFrame, writer: ExcelWriter, sheet_name):
    """DataFrame保存为excel并自动设置列宽"""
    df.to_excel(writer, sheet_name=sheet_name, index=False)
    #  计算表头的字符宽度
    column_widths = (
        df.columns.to_series().apply(lambda x: len(x.encode('gbk'))).values
    )
    #  计算每列的最大字符宽度
    max_widths = (
        df.astype(str).applymap(lambda x: len(x.encode('gbk'))).agg(max).values
    )
    # 计算整体最大宽度
    widths = np.max([column_widths, max_widths], axis=0)
    # 设置列宽
    worksheet = writer.sheets[sheet_name]
    for i, width in enumerate(widths, 1):
        # openpyxl引擎设置字符宽度时会缩水0.5左右个字符，所以干脆+2使左右都空出一个字宽。
        worksheet.column_dimensions[get_column_letter(i)].width = width + 2


def multiple(phone, pas):
    # TODO 验证码图片检测算法需优化  可以使用进入随机时间来进行多线程的操作
    url_list = ["http://210.30.208.126/", "http://210.30.208.140/",
                "http://210.30.208.200/", "http://210.30.208.218/"]
    # 开启4个进程，传入参数
    t1 = Thread(target=scrapy_excel, args=(url_list[0], phone, pas, "2021-2022", 2))
    t1.start()
    t2 = Thread(target=scrapy_excel, args=(url_list[1], phone, pas, "2021-2022", 2))
    t2.start()
    t3 = Thread(target=scrapy_excel, args=(url_list[2], phone, pas, "2021-2022", 2))
    t3.start()
    t4 = Thread(target=scrapy_excel, args=(url_list[3], phone, pas, "2021-2022", 2))
    t4.start()


if __name__ == '__main__':
    # multiple("", "")

    user_name = input("请输入您的账号：")
    pass_word = input("请输入您的密码：")
    print("以下请直接输入数字即可")
    school_year = input("请输入想要查询的学年，例2021-2022：")
    seme_ster = int(input("请输入您想要查询的学期："))
    print("查询中，请稍等...")
    start = time.time()
    scrapy_excel(user_name, pass_word, school_year, seme_ster)
    # 自适应列宽保存数据 调整列宽代码运行时间约为0.25s
    df = pd.read_excel("成绩.xlsx", sheet_name=0)
    with pd.ExcelWriter('成绩.xlsx') as writer:
        excel_auto_column(df, writer, f'TEST')
    end = time.time()
    print("您的成绩已经查询完毕")
    print("本次用时：{}s".format(format(end - start, '.1f')))
